#!/usr/bin/env python

import gtk, gobject, os, sys, time, shutil
from blend.listeners import chatWindowListener, buddyWindowListener
from blend.listeners import trayIconListener, connectionListener
from blend.listeners import notificationListener
from blend.listeners import autoAwayListener
from blend import autoAway
from blend import logger
import mxit.connection as connection
from mxit import handles 
import blend.config, blend.gui.gui, blend.mxitmessages
import logging
import tempfile
import time

_version = "1.1";
_copyright = "(c) 2009 Chris Stranex";
_licence = "GNU General Public Licence 3";

class BlendIT:

   firstTime = True;
   currentlyConnected = False;
   currentAccount = None;
   retrying = -1;
   autoAway = None;
   chatLogger = None;

   def __init__(self):
      self.loadConfiguration();
           
      logging.basicConfig(level=logging.CRITICAL);
      self.logger = logging.getLogger();

      if self.config.debug:
         self.logger.setLevel(logging.INFO);


   def main(self):
      # Create the mxit connection object for later.
      # We can afford to populate it with data if we know it's not the first
      # time they're using BlendIT.     
      if not self.firstTime:
         self.conn = connection.MxitConnection(id = self.currentAccount.username,
                                               password = self.currentAccount.password,
                                               client_id = self.currentAccount.auth,
                                               host = self.config.host,
                                               port = self.config.port,
                                               language = self.currentAccount.lang);
      else:
         self.conn = connection.MxitConnection();

      # Create a temporary directory for the session
      # this will contain temp. downloaded data as well
      # as the splash image.
      self.temp = tempfile.mkdtemp();
      
      # Are we logging?
      self.chatLogger = logger.Logger(self);

      # Create the GUI and other important objects
      self.gui = blend.gui.gui.gui(self);
      self.mxitmessage = blend.mxitmessages.mxitmessages(self);
      
      if self.config.autoAway[0] == True:
         self.autoAway = autoAway.autoAway(self);

      # Create the listeners. They will listen for MXit events.
      # and fire off appropriate actions to each window, tray icon,
      # etc.
      listeners = [
         chatWindowListener.listener(self),
         buddyWindowListener.listener(self),
         trayIconListener.listener(self),
         connectionListener.listener(self),
         autoAwayListener.listener(self),
         notificationListener.listener(self), # This goes last because if a
                                              # notifcation fails we don't
                                              # want it screwing up the rest of
                                              # the program. Do we?
      ];
      for i in range(0,len(listeners)):
         self.conn.listeners.add(listeners[i]);


      # If it's the first tiem, we must pop up the wizard
      # so that the user can enter in their login details

      if self.firstTime:
         self.gui.initiateFirstTimeWindow();
      else:
      	# Otherwise dispaly the main window
         self.gui.initiateWindows();
         self.gui.createTray();
         
         if self.currentAccount.autologin:
            self.login();
         else:
            self.gui.buddyWindow.tree.set_sensitive(False);
            self.gui.buddyWindow.changeMenuToLogOn();
            
      # Once we run this, we can't do anything else
      #gtk.gdk.threads_init()
      gobject.MainLoop().run();
      self.kill();


   def connected(self):
      pass;

   def login(self):
      if not self.currentlyConnected:
         if self.currentAccount.password == '':
            # Ask for password then go
            password = self.gui.requestPassword();
            if password == False:
               # Set offline again
               self.conn.listeners.status_changed(handles.Status.DISCONNECTED,handles.StatusChangeReason.REQUESTED);
               return;
            else:
               self.currentAccount.rememberPassword = False;
               self.currentAccount.password = password;
         if self.conn.password != self.currentAccount.password:
            self.conn.password = self.currentAccount.password;
         gobject.timeout_add(150,self.doLogin);

   def doLogin(self):
      self.conn.connect();
      return False;
      
   def retryLogin(self):
      if self.retrying < 3:
         self.retrying = self.retrying + 1;
         if not self.currentlyConnected:
            self.conn.connect();
         else:
            self.retrying = -1;
      elif self.retrying is not -1:
         self.gui.retryFailError();
         self.retrying = -1;

   def logoff(self):
      if self.currentlyConnected:
         self.disconnect();
         
   def disconnect(self):
      if self.config.offlineMessage[0] == True:
         mesg = self.config.offlineMessage[1];
         # Broadcast only to active chats
         jids = self.gui.chatWindow.convs.lookup;
         for i in range(0,len(jids)):
            conv = self.gui.chatWindow.convs.conv[jids[i]];
            buddy = conv.buddy;
            if not buddy.isService() or buddy.jid != "splash@__Blendit":
               if buddy.presence not in (handles.Presence.OFFLINE,handles.Presence.PENDING): 
                  self.conn.message(buddy,mesg,flags=[handles.MessageFlags.MARKUP]);

      self.conn.close();
      self.currentlyConnected = False;

   def kill(self):
      # Remove the temporary directory
      shutil.rmtree(self.temp);
      # Quit
      sys.exit(0);


   def quit(self):
      if self.currentlyConnected:
         self.disconnect();
      self.kill();

   # Parse the XML configuration from settings.xml
   def loadConfiguration(self):
      if os.path.exists('settings.xml'):
         cfg = blend.config.config();
         
         self.firstTime = cfg.getFirstTime();
         if not self.firstTime:
            self.currentAccount = cfg.getAccount();
         self.config = cfg.getConfig();
      else:
         print "Critical Error: Could not find 'settings.xml'!";
         


if (__name__ == '__main__'):
   try:
      # Change the process name. Does not apply to Windows users
      import ctypes
      libc = ctypes.CDLL('libc.so.6');
      libc.prctl(15,'BlendIt',0,0,0);
   except:
      pass;

   finally:
      try:
         app = BlendIT();
         app.main();
      except KeyboardInterrupt:
         # We want to catch this and make it disconnect first
         app.quit();
         sys.exit(0);